package com.cysoft.starter.log.core.helper;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author 玖零
 * @version v0.0.1
 * @project cysoft-spring-boot-starter-log
 * @package com.cysoft.starter.log.core.helper
 * @date 2025-02-04 23:49
 * @desc 数据库帮助类
 */
public class DataBaseHelper {

    /**
     * 通用协议
     */
    private static final Set<String> COMMON_PROTOCOLS = new HashSet<>(Arrays.asList("mysql", "postgresql", "dm", "kingbasees", "matrixdb"));

    /**
     * 从JDBC URL中提取数据库名称。
     *
     * @param jdbcUrl 要提取数据库名称的JDBC URL。
     * @return 提取的数据库名称。
     * @throws IllegalArgumentException 如果JDBC URL格式不正确。
     */
    public static String extractDatabaseName(String jdbcUrl) {
        //判断jdbcUrl是否为空
        if (jdbcUrl == null || jdbcUrl.isEmpty()) {
            throw new IllegalArgumentException("JDBC URL不能为null或空");
        }

        // 去除jdbc:前缀并分割子协议和子名称
        String[] parts = jdbcUrl.substring(5).split(":", 2);
        if (parts.length != 2) {
            throw new IllegalArgumentException("无法识别的JDBC URL格式");
        }

        // 获取子协议和子名称部分
        String subprotocol = parts[0].toLowerCase();
        String subname = parts[1];

        // 处理不同的子协议
        switch (subprotocol) {
            case "oracle":
                return removeParams(extractOracleDatabaseName(subname));
            case "sqlserver":
                return removeParams(extractSqlServerDatabaseName(subname));
            case "sqlite":
                return removeParams(extractSQLiteDatabaseName(subname));
            case "db2":
                return removeParams(extractDB2DatabaseName(subname));
            case "sybase":
                return removeParams(extractSybaseDatabaseName(subname));
            case "h2":
                return subname;
            default:
                if (COMMON_PROTOCOLS.contains(subprotocol)) {
                    return removeParams(extractDatabaseNameAfterLastSlash(subname));
                } else {
                    throw new IllegalArgumentException("不支持的JDBC子协议:" + subprotocol);
                }
        }
    }

    /**
     * 从子名称中提取数据库名，假定在最后一个斜杠之后。
     * @param subname
     * @return
     */
    private static String extractDatabaseNameAfterLastSlash(String subname) {
        int lastSlashIndex = subname.lastIndexOf('/');
        if (lastSlashIndex == -1) {
            throw new IllegalArgumentException("在JDBC URL中找不到数据库名称");
        }
        return  subname.substring(lastSlashIndex + 1);
    }

    /**
     * 从Oracle JDBC URL中提取数据库名称。
     * @param subname 子名称部分
     * @return 提取的数据库名称
     * @throws IllegalArgumentException 如果无法找到数据库名称
     */
    private static String extractOracleDatabaseName(String subname) {
        int atIndex = subname.indexOf('@');
        if (atIndex == -1) {
            throw new IllegalArgumentException("在Oracle JDBC URL中找不到@符号");
        }
        String dbPart = subname.substring(atIndex + 1);
        int slashIndex = dbPart.indexOf('/');
        if (slashIndex != -1) {
            return dbPart.substring(slashIndex + 1);
        }
        int colonIndex = dbPart.indexOf(':');
        if (colonIndex != -1) {
            return dbPart.substring(colonIndex + 1);
        }
        throw new IllegalArgumentException("在Oracle JDBC URL中找不到数据库名称");
    }

    /**
     * 从SQL Server JDBC URL中提取数据库名称。
     * @param subname 子名称部分
     * @return 提取的数据库名称
     * @throws IllegalArgumentException 如果无法找到数据库名称
     */
    private static String extractSqlServerDatabaseName(String subname) {
        int dbStartIndex = subname.indexOf("databaseName=");
        if (dbStartIndex == -1) {
            throw new IllegalArgumentException("在SQL Server JDBC URL中找不到【databaseName=】标识");
        }
        String dbPart = subname.substring(dbStartIndex + "databaseName=".length());
        int dbEndIndex = dbPart.indexOf(';');
        if (dbEndIndex == -1) {
            return dbPart;
        }
        return dbPart.substring(0, dbEndIndex);
    }

    /**
     * 从SQLite JDBC URL中提取数据库名称。
     * SQLite的子名称通常是数据库文件路径。
     * @param subname 子名称部分
     * @return 提取的数据库名称
     */
    private static String extractSQLiteDatabaseName(String subname) {
        return subname;
    }

    /**
     * 从DB2 JDBC URL中提取数据库名称。
     *
     * @param subname 子名称部分
     * @return 提取的数据库名称
     * @throws IllegalArgumentException 如果无法找到数据库名称
     */
    private static String extractDB2DatabaseName(String subname) {
        int dbNameStartIndex = subname.indexOf("database=");
        if (dbNameStartIndex == -1) {
            throw new IllegalArgumentException("在DB2 JDBC URL中找不到【database=】标识");
        }
        String dbPart = subname.substring(dbNameStartIndex + "database=".length());
        int dbNameEndIndex = dbPart.indexOf(';');
        if (dbNameEndIndex == -1) {
            return dbPart;
        }
        return dbPart.substring(0, dbNameEndIndex);
    }

    /**
     * 从Sybase JDBC URL中提取数据库名称。
     *
     * @param subname 子名称部分
     * @return 提取的数据库名称
     * @throws IllegalArgumentException 如果无法找到数据库名称
     */
    private static String extractSybaseDatabaseName(String subname) {
        int dbNameStartIndex = subname.indexOf("databaseName=");
        if (dbNameStartIndex == -1) {
            throw new IllegalArgumentException("在Sybase JDBC URL中找不到【databaseName=】标识");
        }
        String dbPart = subname.substring(dbNameStartIndex + "databaseName=".length());
        int dbNameEndIndex = dbPart.indexOf(';');
        if (dbNameEndIndex == -1) {
            return dbPart;
        }
        return dbPart.substring(0, dbNameEndIndex);
    }


    /**
     * 去除字符串中的参数部分
     *
     * @param name 包含可能参数的字符串
     * @return 去除参数后的字符串
     */
    private static String removeParams(String name) {
        int questionMarkIndex = name.indexOf('?');
        if (questionMarkIndex != -1) {
            return name.substring(0, questionMarkIndex);
        }
        return name;
    }



}
